﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TriplesGameLogic
{
    public class TriplesGame
    {
        private const int ROWS = 5;
        private const int COLUMNS = 10;

        private char[,] matrix; // A, B, ' '

        public char[] Matrix
        {
            get
            {
                char[] matrix = new char[ROWS * COLUMNS];
                for (int r = 0; r < ROWS; r++)
                {
                    for (int c = 0; c < COLUMNS; c++)
                    {
                        matrix[r * COLUMNS + c] = this.matrix[r, c];
                    }
                }
                return matrix;
            }
        }

        public bool IsGameOver
        {
            get
            {
                return !CanPlayerMove('A') && !CanPlayerMove('B');
            }
        }

        public TriplesGame(char[] matrix)
        {
            this.matrix = new char[ROWS, COLUMNS];

            for (int r = 0; r < ROWS; r++)
            {
                for (int c = 0; c < COLUMNS; c++)
                {
                    int index = r * COLUMNS + c;
                    this.matrix[r, c] = matrix[index];
                }
            }
        }

        public bool TryMakeMove(char player, int x1, int y1, int x2, int y2)
        {
            if (x1 < 0 || x1 >= ROWS || y1 < 0 || y1 >= COLUMNS ||
                x2 < 0 || x2 >= ROWS || y2 < 0 || y2 >= COLUMNS)
            {
                return false;
            }

            NormalizeMove(ref x1, ref y1, ref x2, ref y2);

            if (x1 == x2 && y1 + 2 == y2 || x1 + 2 == x2 && y1 == y2 ||
                x1 + 2 == x2 && y1 + 2 == y2)
            {
                if (CheckCells(player, x1, y1, x2, y2))
                {
                    ExecuteMove(player, x1, y1, x2, y2);
                    return true;
                }
            }
            return false;
        }

        private void NormalizeMove(ref int x1, ref int y1, ref int x2, ref int y2)
        {
            if (x1 == x2)
            {
                if (y1 > y2)
                {
                    IntSwapper(ref y1, ref y2);
                }
            }
            else if(x1 > x2)
            {
                IntSwapper(ref x1, ref x2);
                IntSwapper(ref y1, ref y2);
            }
        }

        private void IntSwapper(ref int a, ref int b)
        {
            int holder = a;
            a = b;
            b = holder;
        }

        private bool CheckCells(char player, int x1, int y1, int x2, int y2)
        {
            int midx = (x1 + x2)/2;
            int midy = (y1 + y2)/2;
            if ((matrix[x1, y1] == player || matrix[x1, y1] == ' ') &&
                (matrix[x2, y2] == player || matrix[x2, y2] == ' ') &&
                (matrix[midx, midy] == player || matrix[midx, midy] == ' '))
            {
                if (matrix[x1, y1] == player && matrix[x2, y2] == player &&
                    matrix[midx, midy] == player)
                {
                    return false;
                }
                return true;
            }
            return false;
        }

        private void ExecuteMove(char player, int x1, int y1, int x2, int y2)
        {
            int midx = (x1 + x2) / 2;
            int midy = (y1 + y2) / 2;
            matrix[x1, y1] = matrix[midx, midy] = matrix[x2, y2] = player;
        }

        public bool CanPlayerMove(char player)
        {
            for (int r = 0; r < ROWS; r++)
            {
                for (int c = 0; c < COLUMNS; c++)
                {
                    if (c + 2 < COLUMNS)
                    {
                        if (CheckCells(player, r, c, r, c + 2))
                        {
                            return true;
                        }
                    }
                    if (r + 2 < ROWS)
                    {
                        if (CheckCells(player, r, c, r + 2, c))
                        {
                            return true;
                        }
                    }
                    if (r + 2 < ROWS && c + 2 < COLUMNS)
                    {
                        if (CheckCells(player, r, c, r + 2, c + 2))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        public int GetPlayerScore(char player)
        {
            int score = 0;
            for (int r = 0; r < ROWS; r++)
            {
                for (int c = 0; c < COLUMNS; c++)
                {
                    if (matrix[r, c] == player)
                    {
                        score++;
                    }
                }
            }
            return score;
        }
    }
}
